home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / nmbd_incomingdgrams.c.z / nmbd_incomingdgrams.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  26.5 KB  |  820 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios routines and daemon - version 2
  5.    Copyright (C) Andrew Tridgell 1994-1998
  6.    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
  7.    Copyright (C) Jeremy Allison 1994-1998
  8.    
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2 of the License, or
  12.    (at your option) any later version.
  13.    
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.    
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.    
  23. */
  24.  
  25. #include "includes.h"
  26.  
  27. extern int DEBUGLEVEL;
  28.  
  29. extern pstring myname;
  30. extern fstring myworkgroup;
  31. extern BOOL found_lm_clients;
  32.  
  33. #if 0
  34.  
  35. /* XXXX note: This function is currently unsuitable for use, as it
  36.    does not properly check that a server is in a fit state to become
  37.    a backup browser before asking it to be one.
  38.    The code is left here to be worked on at a later date.
  39. */
  40.  
  41. /****************************************************************************
  42. Tell a server to become a backup browser
  43. **************************************************************************/
  44.  
  45. void tell_become_backup(void)
  46. {
  47.   struct subnet_record *subrec;
  48.   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
  49.   {
  50.     struct work_record *work;
  51.     for (work = subrec->workgrouplist; work; work = work->next)
  52.     {
  53.       struct server_record *servrec;
  54.       int num_servers = 0;
  55.       int num_backups = 0;
  56.       
  57.       for (servrec = work->serverlist; servrec; servrec = servrec->next)
  58.       {
  59.         num_servers++;
  60.           
  61.         if (is_myname(servrec->serv.name))
  62.           continue;
  63.           
  64.         if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER) 
  65.         {
  66.           num_backups++;
  67.           continue;
  68.         }
  69.           
  70.         if (servrec->serv.type & SV_TYPE_MASTER_BROWSER)
  71.           continue;
  72.           
  73.         if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER))
  74.           continue;
  75.           
  76.         DEBUG(3,("num servers: %d num backups: %d\n", 
  77.               num_servers, num_backups));
  78.           
  79.         /* make first server a backup server. thereafter make every
  80.            tenth server a backup server */
  81.         if (num_backups != 0 && (num_servers+9) / num_backups > 10)
  82.           continue;
  83.           
  84.         DEBUG(2,("sending become backup to %s %s for %s\n",
  85.              servrec->serv.name, inet_ntoa(subrec->bcast_ip),
  86.              work->work_group));
  87.           
  88.         /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
  89.         do_announce_request(servrec->serv.name, work->work_group,
  90.               ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip);
  91.       }
  92.     }
  93.   }
  94. }
  95. #endif
  96.  
  97. /*******************************************************************
  98.   Process an incoming host announcement packet.
  99. *******************************************************************/
  100.  
  101. void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
  102. {
  103.   struct dgram_packet *dgram = &p->packet.dgram;
  104.   int ttl = IVAL(buf,1)/1000;
  105.   char *announce_name = buf+5;
  106.   uint32 servertype = IVAL(buf,23);
  107.   char *comment = buf+31;
  108.   struct work_record *work;
  109.   struct server_record *servrec;
  110.   char *work_name;
  111.   char *source_name = dgram->source_name.name;
  112.  
  113.   comment[43] = 0;
  114.   
  115.   DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
  116. %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
  117.               namestr(&dgram->dest_name),announce_name));
  118.  
  119.   DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
  120.        ttl, servertype,comment));
  121.  
  122.   /* Filter servertype to remove impossible bits. */
  123.   servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
  124.  
  125.   /* A host announcement must be sent to the name WORKGROUP<1d>. */
  126.   if(dgram->dest_name.name_type != 0x1d)
  127.   {
  128.     DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
  129. (was %02x) should be 0x1d. Allowing packet anyway.\n",
  130.               inet_ntoa(p->ip), dgram->dest_name.name_type));
  131.     /* Change it so it was. */
  132.     dgram->dest_name.name_type = 0x1d;
  133.   }
  134.  
  135.   /* For a host announce the workgroup name is the destination name. */
  136.   work_name = dgram->dest_name.name;
  137.  
  138.   /*
  139.    * Syntax servers version 5.1 send HostAnnounce packets to
  140.    * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
  141.    * instead of WORKGROUP<1d> name. So to fix this we check if
  142.    * the workgroup name is our own name, and if so change it
  143.    * to be our primary workgroup name.
  144.    */
  145.  
  146.   if(strequal(work_name, myname))
  147.     work_name = myworkgroup;
  148.  
  149.   /*
  150.    * We are being very agressive here in adding a workgroup
  151.    * name on the basis of a host announcing itself as being
  152.    * in that workgroup. Maybe we should wait for the workgroup
  153.    * announce instead ? JRA.
  154.    */
  155.  
  156.   work = find_workgroup_on_subnet(subrec, work_name);
  157.  
  158.   if(servertype != 0)
  159.   {
  160.     if (work ==NULL )
  161.     {
  162.       /* We have no record of this workgroup. Add it. */
  163.       if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
  164.         return;
  165.     }
  166.   
  167.     if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
  168.     {
  169.       /* If this server is not already in the workgroup, add it. */
  170.       create_server_on_workgroup(work, announce_name, 
  171.                                  servertype|SV_TYPE_LOCAL_LIST_ONLY, 
  172.                                  ttl, comment);
  173.     }
  174.     else
  175.     {
  176.       /* Update the record. */
  177.       servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
  178.       update_server_ttl( servrec, ttl);
  179.       StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
  180.     }
  181.   }
  182.   else
  183.   {
  184.     /*
  185.      * This server is announcing it is going down. Remove it from the 
  186.      * workgroup.
  187.      */
  188.     if(!is_myname(announce_name) && (work != NULL) &&
  189.        ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)
  190.       )
  191.     {
  192.       remove_server_from_workgroup( work, servrec);
  193.     }
  194.   }
  195.   subrec->work_changed = True;
  196. }
  197.  
  198. /*******************************************************************
  199.   Process an incoming WORKGROUP announcement packet.
  200. *******************************************************************/
  201.  
  202. void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
  203. {
  204.   struct dgram_packet *dgram = &p->packet.dgram;
  205.   int ttl = IVAL(buf,1)/1000;
  206.   char *workgroup_announce_name = buf+5;
  207.   uint32 servertype = IVAL(buf,23);
  208.   char *master_name = buf+31;
  209.   struct work_record *work;
  210.   char *source_name = dgram->source_name.name;
  211.  
  212.   master_name[43] = 0;
  213.  
  214.   DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \
  215. %s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
  216.               namestr(&dgram->dest_name),workgroup_announce_name));
  217.  
  218.   DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
  219.            ttl, servertype, master_name));
  220.  
  221.   /* Workgroup announcements must only go to the MSBROWSE name. */
  222.   if (!strequal(dgram->dest_name.name, MSBROWSE) || (dgram->dest_name.name_type != 0x1))
  223.   {
  224.     DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
  225.               inet_ntoa(p->ip), namestr(&dgram->dest_name)));
  226.     return;
  227.   }
  228.  
  229.   if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL)
  230.   {
  231.     /* We have no record of this workgroup. Add it. */
  232.     if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
  233.       return;
  234.   }
  235.   else
  236.   {
  237.     /* Update the workgroup death_time. */
  238.     update_workgroup_ttl(work, ttl);
  239.   }
  240.  
  241.   if(*work->local_master_browser_name == '\0')
  242.   {
  243.     /* Set the master browser name. */
  244.     set_workgroup_local_master_browser_name( work, master_name );
  245.   }
  246.  
  247.   subrec->work_changed = True;
  248. }
  249.  
  250. /*******************************************************************
  251.   Process an incoming local master browser announcement packet.
  252. *******************************************************************/
  253.  
  254. void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
  255. {
  256.   struct dgram_packet *dgram = &p->packet.dgram;
  257.   int ttl = IVAL(buf,1)/1000;
  258.   char *server_name = buf+5;
  259.   uint32 servertype = IVAL(buf,23);
  260.   char *comment = buf+31;
  261.   char *work_name;
  262.   struct work_record *work;
  263.   struct server_record *servrec;
  264.   char *source_name = dgram->source_name.name;
  265.  
  266.   comment[43] = 0;
  267.  
  268.   DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
  269. %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
  270.               namestr(&dgram->dest_name),server_name));
  271.  
  272.   DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
  273.            ttl, servertype, comment));
  274.  
  275.   /* A local master announcement must be sent to the name WORKGROUP<1e>. */
  276.   if(dgram->dest_name.name_type != 0x1e)
  277.   {
  278.     DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
  279. (was %02x) should be 0x1e. Ignoring packet.\n",
  280.               inet_ntoa(p->ip), dgram->dest_name.name_type));
  281.     return;
  282.   }
  283.  
  284.   /* Filter servertype to remove impossible bits. */
  285.   servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
  286.  
  287.   /* For a local master announce the workgroup name is the destination name. */
  288.   work_name = dgram->dest_name.name;
  289.  
  290.   if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL)
  291.   {
  292.     /* Don't bother adding if it's a local master release announce. */
  293.     if(servertype == 0)
  294.       return;
  295.  
  296.     /* We have no record of this workgroup. Add it. */
  297.     if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
  298.       return;
  299.   }
  300.  
  301.   /* If we think we're the local master browser for this workgroup,
  302.      we should never have got this packet. We don't see our own
  303.      packets.
  304.    */
  305.   if(AM_LOCAL_MASTER_BROWSER(work))
  306.   {
  307.     DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
  308. a local master browser for workgroup %s and we think we are master. Forcing election.\n",
  309.       server_name, inet_ntoa(p->ip), work_name));
  310.  
  311.     /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
  312.        they have become a local master browser once, they will never
  313.        stop sending local master announcements. To fix this we send
  314.        them a reset browser packet, with level 0x2 on the __SAMBA__
  315.        name that only they should be listening to. */
  316.    
  317.     send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);
  318.  
  319.     /* We should demote ourself and force an election. */
  320.  
  321.     unbecome_local_master_browser( subrec, work, True);
  322.  
  323.     /* The actual election requests are handled in
  324.        nmbd_election.c */
  325.     return;
  326.   }  
  327.  
  328.   /* Find the server record on this workgroup. If it doesn't exist, add it. */
  329.  
  330.   if(servertype != 0)
  331.   {
  332.     if((servrec = find_server_in_workgroup( work, server_name))==NULL)
  333.     {
  334.       /* If this server is not already in the workgroup, add it. */
  335.       create_server_on_workgroup(work, server_name, 
  336.                                  servertype|SV_TYPE_LOCAL_LIST_ONLY, 
  337.                                  ttl, comment);
  338.     }
  339.     else
  340.     {
  341.       /* Update the record. */
  342.       servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
  343.       update_server_ttl(servrec, ttl);
  344.       StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
  345.     }
  346.  
  347.     set_workgroup_local_master_browser_name( work, server_name );
  348.   }
  349.   else
  350.   {
  351.     /*
  352.      * This server is announcing it is going down. Remove it from the
  353.      * workgroup.
  354.      */
  355.     if(!is_myname(server_name) && (work != NULL) &&
  356.        ((servrec = find_server_in_workgroup( work, server_name))!=NULL)
  357.       )
  358.     {
  359.       remove_server_from_workgroup( work, servrec);
  360.     }
  361.   }
  362.  
  363.   subrec->work_changed = True;
  364. }
  365.  
  366. /*******************************************************************
  367.   Process a domain master announcement frame.
  368.   Domain master browsers receive these from local masters. The Domain
  369.   master should then issue a sync with the local master, asking for
  370.   that machines local server list.
  371. ******************************************************************/
  372.  
  373. void process_master_browser_announce(struct subnet_record *subrec, 
  374.                                      struct packet_struct *p,char *buf)
  375. {
  376.   char *local_master_name = buf;
  377.   struct work_record *work;
  378.   struct browse_cache_record *browrec;
  379.  
  380.   local_master_name[15] = 0;
  381.   
  382.   DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",
  383.            local_master_name, inet_ntoa(p->ip)));
  384.   
  385.   if (!lp_domain_master()) 
  386.   {
  387.     DEBUG(0,("process_master_browser_announce: Not configured as domain \
  388. master - ignoring master announce.\n"));
  389.     return;
  390.   }
  391.   
  392.   if((work = find_workgroup_on_subnet(subrec, myworkgroup)) == NULL)
  393.   {
  394.     DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",
  395.            myworkgroup, subrec->subnet_name));
  396.     return;
  397.   }
  398.  
  399.   if(!AM_DOMAIN_MASTER_BROWSER(work))
  400.   {
  401.     DEBUG(0,("process_master_browser_announce: Local master announce made to us from \
  402. %s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip)));
  403.     return;
  404.   }
  405.  
  406.   /* Add this host as a local master browser entry on the browse lists.
  407.      This causes a sync request to be made to it at a later date.
  408.    */
  409.  
  410.   if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL)
  411.   {
  412.     /* Add it. */
  413.     create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);
  414.   }
  415.   else
  416.     update_browser_death_time(browrec);
  417. }
  418.  
  419. /*******************************************************************
  420.   Process an incoming LanMan host announcement packet.
  421. *******************************************************************/
  422.  
  423. void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
  424. {
  425.   struct dgram_packet *dgram = &p->packet.dgram;
  426.   uint32 servertype = IVAL(buf,1);
  427.   int osmajor=CVAL(buf,5);           /* major version of node software */
  428.   int osminor=CVAL(buf,6);           /* minor version of node software */
  429.   int ttl = SVAL(buf,7);
  430.   char *announce_name = buf+9;
  431.   struct work_record *work;
  432.   struct server_record *servrec;
  433.   char *work_name;
  434.   char *source_name = dgram->source_name.name;
  435.   pstring comment;
  436.   char *s = buf+9;
  437.  
  438.   s = skip_string(s,1);
  439.   StrnCpy(comment, s, 43);
  440.  
  441.   DEBUG(3,("process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \
  442. %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
  443.               namestr(&dgram->dest_name),announce_name));
  444.  
  445.   DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",
  446.           osmajor, osminor, ttl, servertype,comment));
  447.  
  448.   if ((osmajor < 36) || (osmajor > 38) || (osminor !=0))
  449.   {
  450.     DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \
  451. originate from OS/2 Warp client. Ignoring packet.\n"));
  452.     /* Could have been from a Windows machine (with its LM Announce enabled),
  453.        or a Samba server. Then don't disrupt the current browse list. */
  454.     return;
  455.   }
  456.  
  457.   /* Filter servertype to remove impossible bits. */
  458.   servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
  459.  
  460.   /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
  461.   if(dgram->dest_name.name_type != 0x00)
  462.   {
  463.     DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \
  464. (was %02x) should be 0x00. Allowing packet anyway.\n",
  465.               inet_ntoa(p->ip), dgram->dest_name.name_type));
  466.     /* Change it so it was. */
  467.     dgram->dest_name.name_type = 0x00;
  468.   }
  469.  
  470.   /* For a LanMan host announce the workgroup name is the destination name. */
  471.   work_name = dgram->dest_name.name;
  472.  
  473.   /*
  474.    * Syntax servers version 5.1 send HostAnnounce packets to
  475.    * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
  476.    * instead of WORKGROUP<1d> name. So to fix this we check if
  477.    * the workgroup name is our own name, and if so change it
  478.    * to be our primary workgroup name. This code is probably
  479.    * not needed in the LanMan announce code, but it won't hurt.
  480.    */
  481.  
  482.   if(strequal(work_name, myname))
  483.     work_name = myworkgroup;
  484.  
  485.   /*
  486.    * We are being very agressive here in adding a workgroup
  487.    * name on the basis of a host announcing itself as being
  488.    * in that workgroup. Maybe we should wait for the workgroup
  489.    * announce instead ? JRA.
  490.    */
  491.  
  492.   work = find_workgroup_on_subnet(subrec, work_name);
  493.  
  494.   if(servertype != 0)
  495.   {
  496.     if (work == NULL)
  497.     {
  498.       /* We have no record of this workgroup. Add it. */
  499.       if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
  500.         return;
  501.     }
  502.  
  503.     if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
  504.     {
  505.       /* If this server is not already in the workgroup, add it. */
  506.       create_server_on_workgroup(work, announce_name,
  507.                                  servertype|SV_TYPE_LOCAL_LIST_ONLY,
  508.                                  ttl, comment);
  509.     }
  510.     else
  511.     {
  512.       /* Update the record. */
  513.       servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
  514.       update_server_ttl( servrec, ttl);
  515.       StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
  516.     }
  517.   }
  518.   else
  519.   {
  520.     /*
  521.      * This server is announcing it is going down. Remove it from the
  522.      * workgroup.
  523.      */
  524.     if(!is_myname(announce_name) && (work != NULL) &&
  525.        ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)
  526.       )
  527.     {
  528.       remove_server_from_workgroup( work, servrec);
  529.     }
  530.   }
  531.  
  532.   subrec->work_changed = True;
  533.   found_lm_clients = True;
  534. }
  535.  
  536. /****************************************************************************
  537.   Send a backup list response.
  538. *****************************************************************************/
  539.  
  540. static void send_backup_list_response(struct subnet_record *subrec, 
  541.                              struct work_record *work,
  542.                              struct nmb_name *send_to_name,
  543.                              unsigned char max_number_requested,
  544.                  uint32 token, struct in_addr sendto_ip)
  545. {                     
  546.   char outbuf[1024];
  547.   char *p, *countptr, *nameptr;
  548.   unsigned int count = 0;
  549.   int len;
  550.   struct server_record *servrec;
  551.  
  552.   bzero(outbuf,sizeof(outbuf));
  553.  
  554.   DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
  555.        work->work_group, namestr(send_to_name), inet_ntoa(sendto_ip)));
  556.   
  557.   p = outbuf;
  558.   
  559.   SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
  560.   p++;
  561.  
  562.   countptr = p;
  563.   p++;
  564.  
  565.   SIVAL(p,0,token); /* The sender's unique info. */
  566.   p += 4;
  567.   
  568.   nameptr = p;
  569.  
  570.   /* We always return at least one name - our own. */
  571.   count = 1;
  572.   StrnCpy(p,myname,15);
  573.   strupper(p);
  574.   p = skip_string(p,1);
  575.  
  576.   /* Look for backup browsers in this workgroup. */
  577.   for (servrec = work->serverlist; servrec; servrec = servrec->next)
  578.   { 
  579.     len = PTR_DIFF(p, outbuf);
  580.     if((sizeof(outbuf) - len) < 16)
  581.       break;
  582.  
  583.     if(count >= (unsigned int)max_number_requested)
  584.       break;
  585.  
  586.     if(strnequal(servrec->serv.name, myname,15))
  587.       continue;
  588.  
  589.     if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER))
  590.       continue;
  591.  
  592.     StrnCpy(p, servrec->serv.name, 15);
  593.     strupper(p);
  594.     count++;
  595.  
  596.     DEBUG(5,("send_backup_list_response: Adding server %s number %d\n",
  597.               p, count));
  598.  
  599.     p = skip_string(p,1);
  600.   }
  601.  
  602.   SCVAL(countptr, 0, count);
  603.  
  604.   len = PTR_DIFF(p, outbuf);
  605.  
  606.   DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
  607.           send_to_name->name, inet_ntoa(sendto_ip), count));
  608.  
  609.   send_mailslot(True, BROWSE_MAILSLOT,
  610.                 outbuf,PTR_DIFF(p,outbuf),
  611.                 myname, 0, 
  612.                 send_to_name->name,0,
  613.                 sendto_ip, subrec->myip);
  614. }
  615.  
  616. /*******************************************************************
  617.   Process a send backup list request packet.
  618.  
  619.   A client sends a backup list request to ask for a list of servers on
  620.   the net that maintain server lists for a domain. A server is then
  621.   chosen from this list to send NetServerEnum commands to to list
  622.   available servers.
  623.  
  624. ********************************************************************/
  625.  
  626. void process_get_backup_list_request(struct subnet_record *subrec,
  627.                                      struct packet_struct *p,char *buf)
  628. {
  629.   struct dgram_packet *dgram = &p->packet.dgram;
  630.   struct work_record *work;
  631.   unsigned char max_number_requested = CVAL(buf,0);
  632.   uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
  633.   int name_type = dgram->dest_name.name_type;
  634.   char *workgroup_name = dgram->dest_name.name;
  635.  
  636.   DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
  637.            namestr(&dgram->source_name), inet_ntoa(p->ip),
  638.            namestr(&dgram->dest_name)));
  639.   
  640.   /* We have to be a master browser, or a domain master browser
  641.      for the requested workgroup. That means it must be our
  642.      workgroup. */
  643.  
  644.   if(strequal(workgroup_name, myworkgroup) == False)
  645.   {
  646.     DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
  647.            workgroup_name));
  648.     return;
  649.   }
  650.  
  651.   if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
  652.   {
  653.     DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
  654. subnet %s.\n", workgroup_name, subrec->subnet_name));
  655.     return;
  656.   }
  657.  
  658.   if(name_type == 0x1b)
  659.   {
  660.     /* We must be a domain master browser in order to
  661.        process this packet. */
  662.  
  663.     if(!AM_DOMAIN_MASTER_BROWSER(work))
  664.     {
  665.       DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
  666. and I am not a domain master browser.\n", workgroup_name));
  667.       return;
  668.     }
  669.   }
  670.   else if (name_type == 0x1d)
  671.   {
  672.     /* We must be a local master browser in order to
  673.        process this packet. */
  674.  
  675.     if(!AM_LOCAL_MASTER_BROWSER(work))
  676.     {
  677.       DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
  678. and I am not a local master browser.\n", workgroup_name));
  679.       return;
  680.     }
  681.   }
  682.   else
  683.   {
  684.     DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
  685.             name_type));
  686.     return;
  687.   }
  688.  
  689.   send_backup_list_response(subrec, work, &dgram->source_name, 
  690.                             max_number_requested, token, p->ip);
  691. }
  692.  
  693. /*******************************************************************
  694.   Process a reset browser state packet.
  695.  
  696.   Diagnostic packet:
  697.   0x1 - Stop being a master browser and become a backup browser.
  698.   0x2 - Discard browse lists, stop being a master browser, try again.
  699.   0x4 - Stop being a master browser forever.
  700.          
  701. ******************************************************************/
  702.  
  703. void process_reset_browser(struct subnet_record *subrec,
  704.                                   struct packet_struct *p,char *buf)
  705. {
  706.   struct dgram_packet *dgram = &p->packet.dgram;
  707.   int state = CVAL(buf,0);
  708.   struct subnet_record *sr;
  709.  
  710.   DEBUG(1,("process_reset_browser: received diagnostic browser reset \
  711. request from %s IP %s state=0x%X\n",
  712.              namestr(&dgram->source_name), inet_ntoa(p->ip), state));
  713.  
  714.   /* Stop being a local master browser on all our broadcast subnets. */
  715.   if (state & 0x1)
  716.   {
  717.     for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr))
  718.     {
  719.       struct work_record *work;
  720.       for (work = sr->workgrouplist; work; work = work->next)
  721.       {
  722.         if (AM_LOCAL_MASTER_BROWSER(work))
  723.           unbecome_local_master_browser(sr, work, True);
  724.       }
  725.     }
  726.   }
  727.   
  728.   /* Discard our browse lists. */
  729.   if (state & 0x2)
  730.   {
  731.     /*
  732.      * Calling expire_workgroups_and_servers with a -1
  733.      * time causes all servers not marked with a PERMANENT_TTL
  734.      * on the workgroup lists to be discarded, and all 
  735.      * workgroups with empty server lists to be discarded.
  736.      * This means we keep our own server names and workgroup
  737.      * as these have a PERMANENT_TTL.
  738.      */
  739.  
  740.     expire_workgroups_and_servers(-1);
  741.   }
  742.   
  743.   /* Request to stop browsing altogether. */
  744.   if (state & 0x4)
  745.     DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
  746. }
  747.  
  748. /*******************************************************************
  749.   Process an announcement request packet.
  750.   We don't respond immediately, we just check it's a request for
  751.   our workgroup and then set the flag telling the announce code
  752.   in nmbd_sendannounce.c:announce_my_server_names that an 
  753.   announcement is needed soon.
  754. ******************************************************************/
  755.  
  756. void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
  757. {
  758.   struct dgram_packet *dgram = &p->packet.dgram;
  759.   struct work_record *work;
  760.   char *workgroup_name = dgram->dest_name.name;
  761.  
  762.   DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
  763.            namestr(&dgram->source_name), inet_ntoa(p->ip),
  764.            namestr(&dgram->dest_name)));
  765.   
  766.   /* We only send announcement requests on our workgroup. */
  767.   if(strequal(workgroup_name, myworkgroup) == False)
  768.   {
  769.     DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
  770.            workgroup_name));
  771.     return;
  772.   }
  773.  
  774.   if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
  775.   {
  776.     DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
  777.             workgroup_name));
  778.     return;
  779.   }
  780.  
  781.   work->needannounce = True;
  782. }
  783.  
  784. /*******************************************************************
  785.   Process a LanMan announcement request packet.
  786.   We don't respond immediately, we just check it's a request for
  787.   our workgroup and then set the flag telling that we have found
  788.   a LanMan client (DOS or OS/2) and that we will have to start
  789.   sending LanMan announcements (unless specifically disabled
  790.   through the "lm announce" parameter in smb.conf)
  791. ******************************************************************/
  792.  
  793. void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
  794. {
  795.   struct dgram_packet *dgram = &p->packet.dgram;
  796.   struct work_record *work;
  797.   char *workgroup_name = dgram->dest_name.name;
  798.  
  799.   DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
  800.            namestr(&dgram->source_name), inet_ntoa(p->ip),
  801.            namestr(&dgram->dest_name)));
  802.  
  803.   /* We only send announcement requests on our workgroup. */
  804.   if(strequal(workgroup_name, myworkgroup) == False)
  805.   {
  806.     DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
  807.            workgroup_name));
  808.     return;
  809.   }
  810.  
  811.   if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
  812.   {
  813.     DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
  814.             workgroup_name));
  815.     return;
  816.   }
  817.  
  818.   found_lm_clients = True;
  819. }
  820.